package org.example.util;

import org.example.bean.annotation.ExcelColumn;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author huangshen
 * @version 0.0.3
 * @description scanUtil
 * @since 2022/1/6 9:32
 */
public class scanUtil {
    private List<File> fileList = new LinkedList<>();
    // 需要扫描的包名 目前暂定只读 后续若bean项目膨胀过大，可通过构造函数传入指定包
    private static final String packageName = "org.test";
    // ExcelBean注解中的 excelName
    private final String excelTitle;

    public scanUtil(String excelTitle) {
        this.excelTitle = excelTitle;
    }

    /**
     * 扫描目标包，找出指定bean类
     */
    public void getColumnList(List<String> paramList) {
        try {
            String servicePath = packageName.replace('.', '/');
            URL url = scanUtil.class.getClassLoader().getResource(servicePath);
            int indexUrl = url.toString().indexOf("!/");
            if (indexUrl < 0) {
                doPath(new File(url.toURI()));


                for (File file : fileList) {
                    paramRegister(paramList, packageName, file);
                }
                return;
            }

            String jarPath = url.toString().substring(0, url.toString().indexOf("!/") + 2);
            URL jarURL = new URL(jarPath);
            JarURLConnection jarURLConnection = (JarURLConnection) jarURL.openConnection();
            JarFile jarFile = jarURLConnection.getJarFile();
            Enumeration<JarEntry> jarEntrys = jarFile.entries();
            while (jarEntrys.hasMoreElements()) {
                JarEntry entry = jarEntrys.nextElement();
                String name = entry.getName();
                if (name.startsWith(servicePath) && !entry.isDirectory()) {
                    File file = new File(name);
                    paramRegister(paramList, packageName, file);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据对象参数的ExcelColumnName注解，将注解中的columnName放入集合中
     *
     * @param paramList 返回的参数集合
     */
    public void paramRegister(List<String> paramList, String packageName, File file) {
        try {
            int index = file.getName().lastIndexOf(".");
            String clsName = file.getName().substring(0, index);
            String clsPath = packageName + "." + clsName;
            try {
                System.out.println(file.getCanonicalPath().replace(".", "\\").lastIndexOf(packageName));
            } catch (IOException e) {
                e.printStackTrace();
            }
            Class<?> clss = Class.forName(clsPath);
            Field[] fields = clss.getFields();
            for (Field field : fields) {
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                if (!Function.equalsNull(annotation)) {
                    paramList.add(annotation.name());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 该方法会得到所有的类，将类的File写入到fileList中
     *
     * @param file
     */
    private void doPath(File file) {
        // 文件夹
        if (file.isDirectory()) {
            // 文件夹就递归
            File[] files = file.listFiles();
            for (File f : files) {
                doPath(f);
            }
        }
        // 标准文件判断是否是class文件
        if (file.getName().endsWith(".class")) {
            // 如果是放入集合中
            fileList.add(file);
        }
    }
}
